#import "../3Dincludes.h"
#import "Sphere.h"
@implementation Sphere

static int shapeNumber = 1;
- (int)shapeNumber
{
    return shapeNumber++;
}

- calcBoundingBox
{
// xmin & xmax
    boundingBox[0]=-radius;
    boundingBox[1]=radius;
    
// ymin & ymax
    boundingBox[2]=-radius; 
    boundingBox[3]=radius;  
    
// zmin & zmax
    boundingBox[4]=zMin;
    boundingBox[5]=zMax;
    return self;
}

- init
{
    [super init];
    radius = 1.;
    zMax = 1.;
    zMin = -1.;
    thetaMax = 360.;
    [self calcBoundingBox];
    return self;
}

- setRadius:(RtFloat *) aRad
{
    [super setRadius:aRad];
    [self calcBoundingBox];
    return self;
}

- setZMax:(RtFloat *)z;
{
    [super setZMax:z];
    [self calcBoundingBox];
    return self;
}

- setZMin:(RtFloat *)z;
{
    [super setZMin:z];
    [self calcBoundingBox];
    return self;
}

/* SolidSphere: create a closed sphere */
void
SolidSphere(rad, zmin, zmax)
RtFloat rad, zmin, zmax;
{
    RiSolidBegin(RI_PRIMITIVE);

        RiSphere(rad, zmin, zmax, 360.0, RI_NULL);

        if(fabs(zmax) < rad)        /* The top is chopped off       */
            RiDisk(zmax, sqrt(rad*rad - zmax*zmax), 360.0, RI_NULL);
        
        if(fabs(zmin) < rad)        /* The bottom is chopped off    */ 
            RiDisk(zmin, sqrt(rad*rad - zmin*zmin), 360.0, RI_NULL);
        
    RiSolidEnd();
}

    /*
     *  SolidCylinder() makes a solid cylinder of the given radius, extending
     *  from zmin to zmax along the z axis.
     */
void
SolidCylinder(rad, zmin, zmax)
float rad, zmin, zmax;
{
    RiSolidBegin(RI_PRIMITIVE);

        RiCylinder(rad, zmin, zmax, 360.0, RI_NULL);

        RiDisk(zmax, rad, 360.0, RI_NULL);       /* Close the top    */
        RiDisk(zmin, rad, 360.0, RI_NULL);       /* Close the bottom */

    RiSolidEnd(); 
}


/* SolidHemisphere: create a solid hemisphere from a sphere and a cylinder*/
void
SolidHemisphere(rad, zmin, zmax)
float rad, zmin, zmax;
{
    RiSolidBegin(RI_INTERSECTION);
        SolidSphere(rad, zmin, zmax);
        /*
         * A cylinder is defined with the same radius as the sphere and
         * rotated so that its bottom bisects the sphere in the x/z plane.
         */
        RiRotate(90.0, 1.0, 0.0, 0.0); 
        /* Rotate the cylinder 90 degrees in x */
        SolidCylinder(rad, 0.0, rad);
    RiSolidEnd();                 /* intersection */
}

void
SolidWedge(rad, zmin, zmax, thetamax)
float rad, zmin, zmax, thetamax;
{
    if (thetamax == 180.0) {
        SolidHemisphere(rad, zmin, zmax);
    } else if (thetamax == 360.0) {
        SolidSphere(rad, zmin, zmax);
    } else if (thetamax < 180.0) {
        RiSolidBegin(RI_INTERSECTION);
            SolidHemisphere(rad, zmin, zmax);
            RiRotate(thetamax-180.0, 0.0, 0.0, 1.0);
            SolidHemisphere(rad, zmin, zmax);
        RiSolidEnd();
    } else if (thetamax < 360.0) {
        RiSolidBegin(RI_UNION);
            SolidHemisphere(rad, zmin, zmax);
            RiRotate(thetamax, 0.0, 0.0, 1.0);
            SolidHemisphere(rad, zmin, zmax);
        RiSolidEnd();
    }
}

- doRenderSelf: (Camera *) camera
{
    if(![super doRenderSelf:camera]) return nil;
    
    if (shFlags.isSolid)
	SolidWedge(radius,zMin,zMax,thetaMax);
    else 
	RiSphere(radius,zMin,zMax,thetaMax,RI_NULL);
    return self;
}
@end
